package developer.算法.链表.合并K个升序列表;

/**
 * 给你一个链表数组，每个链表都已经按升序排列。
 * 请你将所有链表合并到一个升序链表中，返回合并后的链表。
 * 输入：lists = [[1,4,5],[1,3,4],[2,6]]
 * 输出：[1,1,2,3,4,4,5,6]
 * 解释：链表数组如下：
 * [
 * 1->4->5,
 * 1->3->4,
 * 2->6
 * ]
 * 将它们合并到一个有序链表中得到。
 * 1->1->2->3->4->4->5->6
 * 示例 2：
 * <p>
 * 输入：lists = []
 * 输出：[]
 * 示例 3：
 * <p>
 * 输入：lists = [[]]
 * 输出：[]
 */
public class HeBingKGeShengXuLieBiao {

    public static void main(String[] args) {

        Solution solution = new Solution();

        ListNode listNode = solution.mergeKLists(
                new ListNode[]{
                        new ListNode(1, new ListNode(4, new ListNode(5))),
                        new ListNode(1, new ListNode(3, new ListNode(4))),
                        new ListNode(2, new ListNode(6)),
                }
        );

        if (listNode != null) {
            while (listNode != null) {
                System.out.println(listNode.val);
                listNode = listNode.next;
            }
        }
    }

    public static ListNode mergeKLists(ListNode[] lists) {
        return merge(lists, 0, lists.length - 1);
    }


    static class Solution {
        public ListNode mergeKLists(ListNode[] lists) {
            return merge(lists, 0, lists.length - 1);
        }

        public ListNode merge(ListNode[] lists, int left, int right) {
            if (left == right) {
                return lists[left];
            }
            int mid = left + (right - left) / 2;

            return merge2ListNodes(merge(lists, left, mid), merge(lists, mid + 1, right));
        }
    }

    // 1 2
    // 3 4
    public static ListNode merge(ListNode[] lists, int l, int r) {
        if (l == r) {
            return lists[l];//这里是核心  left==right 返回一个 递归的终点
        }
        if (l > r) {
            return null;
        }

        int mid = (l + r) / 2;
        //分治法
        return merge2ListNodes(merge(lists, l, mid), merge(lists, mid + 1, r));
    }

    public static ListNode merge2ListNodes(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        }
        if (l2 == null) {
            return l1;
        }
        ListNode header = new ListNode();
        ListNode current = header;
        while (l1 != null && l2 != null) {

            int valL1 = l1.val;
            int valL2 = l2.val;
            if (valL1 > valL2) {
                current.next = l2;
                l2 = l2.next;

            } else {
                current.next = l1;
                l1 = l1.next;
            }
            current = current.next;
        }
        current.next = l1 == null ? l2 : l1;
        return header.next;
    }

    public static class ListNode {
        int val;
        ListNode next;

        ListNode() {
        }

        ListNode(int val) {
            this.val = val;
        }

        ListNode(int val, ListNode next) {
            this.val = val;
            this.next = next;
        }
    }
}
